home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Framework / Sources / UMacAppGlobals.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  39.1 KB  |  1,395 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UMacAppGlobals.cp 
  3. // Copyright © 1984-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UMACAPPGLOBALS__
  7. #include "UMacAppGlobals.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. //    #ifndef __UAPPLICATION__
  13. //    #include "UApplication.h"
  14. //    #endif
  15.  
  16. #ifndef __UBUSYCURSOR__
  17. #include "UBusyCursor.h"
  18. #endif
  19.  
  20. #ifndef __UCLIPBOARDMGR__
  21. #include "UClipboardMgr.h"
  22. #endif
  23.  
  24. #if qContainer
  25.     #ifndef __UCONTAINER__
  26.     #include "UContainer.h"
  27.     #endif
  28. #endif
  29.  
  30. #ifndef __UCONTROL__
  31. #include "UControl.h"
  32. #endif
  33.  
  34. #ifndef __UDEBUG__
  35. #include "UDebug.h"
  36. #endif
  37.  
  38. //    #ifndef __UDIALOG__
  39. //    #include "UDialog.h"
  40. //    #endif
  41.  
  42. #ifndef __UDISPATCHER__
  43. #include "UDispatcher.h"
  44. #endif
  45.  
  46. #ifndef __UDOCUMENT__
  47. #include "UDocument.h"
  48. #endif
  49.  
  50. // always include for TDragDropBehavior stub
  51. #ifndef __UDRAGDROBEHAVIOR__
  52. #include "UDragDropBehavior.h"
  53. #endif
  54.  
  55. #ifndef __UDRAWINGENVIRONMENT__
  56. #include "UDrawingEnvironment.h"
  57. #endif
  58.  
  59. #ifndef __UERRORMGR__
  60. #include "UErrorMgr.h"
  61. #endif
  62.  
  63. #ifndef __UMACAPPUTILITIES__
  64. #include "UMacAppUtilities.h"
  65. #endif
  66.  
  67. #ifndef __UMEMORY__
  68. #include "UMemory.h"
  69. #endif
  70.  
  71. #ifndef __UMENUMGR__
  72. #include "UMenuMgr.h"
  73. #endif
  74.  
  75. #ifndef __UNIVERSALSTARTUP__
  76. #include "UniversalStartup.h"
  77. #endif
  78.  
  79. #ifndef __UPATCH__
  80. #include "UPatch.h"
  81. #endif
  82.  
  83. #ifndef __UPRINTHANDLER__
  84. #include "UPrintHandler.h"
  85. #endif
  86.  
  87. #ifndef __USCRIPTING__
  88. #include "UScripting.h"
  89. #endif
  90.  
  91. #ifndef __USCROLLER__
  92. #include "UScroller.h"
  93. #endif
  94.  
  95. #ifndef __USEGMENTS__
  96. #include "USegments.h"
  97. #endif
  98.  
  99. #ifndef __UUNDO__
  100. #include "UUndo.h"
  101. #endif
  102.  
  103. #ifndef __UWINDOW__
  104. #include "UWindow.h"
  105. #endif
  106.  
  107. // CALib
  108.  
  109. #if qContainer
  110.     #ifndef _CALIB_
  111.     #include "CALib.h"
  112.     #endif
  113. #endif
  114.  
  115. // Toolbox
  116.  
  117. #ifndef __ERRORS__
  118. #include <Errors.h>
  119. #endif
  120.  
  121. #ifndef __FOLDERS__
  122. #include <Folders.h>
  123. #endif
  124.  
  125. #ifndef __FONTS__
  126. #include <Fonts.h>
  127. #endif
  128.  
  129. #ifndef __GESTALT__
  130. #include <Gestalt.h>
  131. #endif
  132.  
  133. #ifndef __RESOURCES__
  134. #include <Resources.h>
  135. #endif
  136.  
  137. #ifndef __TOOLUTILS__
  138. #include <ToolUtils.h>
  139. #endif
  140.  
  141. #ifndef __TRAPS__
  142. #include <Traps.h>
  143. #endif
  144.  
  145. // ANSI
  146.  
  147. #ifndef __STDIO__
  148. #include <stdio.h>
  149. #endif
  150.  
  151. #ifndef __STDLIB__
  152. #include <stdlib.h>
  153. #endif
  154.  
  155. //----------------------------------------------------------------------------------------
  156. #if !defined(__MWERKS__)
  157. QDGlobals qd;
  158. #endif
  159.  
  160. TextStyle gSystemStyle;
  161. TextStyle gApplicationStyle;
  162. TextStyle gApplicationStyle9;
  163.  
  164. WindowRef gWorkPort;
  165.  
  166. RgnHandle gTemporaryRegion;
  167.  
  168. RgnHandle CTemporaryRegion::fCachedRgn;
  169.  
  170. NMRecPtr gNotificationPtr;
  171.  
  172. ModalFilterYDProcPtr gModalFilterYDProcPtr = MacAppStandardFileFilter;
  173.     
  174. #if qDebug
  175. Boolean gBusyTemporaryRegion;
  176. CStr255 gUsedBy;
  177. #endif
  178.  
  179. FailInfo pFi;
  180.  
  181. //========================================================================================
  182. // GLOBAL Procedures
  183. //========================================================================================
  184. static pascal void ExitToShellCleanupMacApp(void);
  185. static short FindPos(const CStr255& pattern, CStr255& source);
  186.  
  187. //========================================================================================
  188. // CLASS PatchExitToShell
  189. //========================================================================================
  190. #pragma segment MAGlobalsRes
  191.  
  192. typedef pascal void (*ExitToShellType)(void);
  193.  
  194. #if GENERATINGCFM
  195. typedef UniversalProcPtr ExitToShellUPP;
  196. #else
  197. typedef ProcPtr ExitToShellUPP;
  198. #endif
  199.     
  200. enum
  201. {
  202.     uppExitToShellProcInfo = kPascalStackBased
  203. };
  204.  
  205. #if GENERATINGCFM
  206. #define NewExitToShellProc(userRoutine)  \
  207.         (ExitToShellUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppExitToShellProcInfo, GetCurrentISA())
  208. #else
  209. #define NewExitToShellProc(userRoutine)        \
  210.         ((ExitToShellUPP) (userRoutine))
  211. #endif
  212.     
  213. #if GENERATINGCFM
  214. #define CallExitToShellProc(userRoutine)        \
  215.         CallUniversalProc((UniversalProcPtr)(userRoutine), uppExitToShellProcInfo)
  216. #else
  217. #define CallExitToShellProc(userRoutine)        \
  218.         (*(userRoutine))()
  219. #endif
  220.     
  221. class PatchExitToShell : public TrapPatch
  222. {
  223.   public:
  224.     void Install(ExitToShellType routine);
  225.     void CallInherited(void);
  226. };
  227.  
  228. //--------------------------------------------------------------------------------------------------
  229. #pragma segment MAInit
  230.  
  231. void PatchExitToShell::Install(ExitToShellType routine)
  232. {
  233.     patchRoutine = NewExitToShellProc(StripLong(routine));
  234.     FailNIL(patchRoutine);
  235.     PatchTrap(_ExitToShell, patchRoutine);
  236. }
  237.  
  238. //--------------------------------------------------------------------------------------------------
  239. #pragma segment MAGlobalsRes
  240.  
  241. void PatchExitToShell::CallInherited(void)
  242. {
  243.     CallExitToShellProc((ExitToShellType) oldTrapAddr);
  244. }
  245.  
  246. //--------------------------------------------------------------------------------------------------
  247.  
  248. static PatchExitToShell pETSPatch;
  249.  
  250. //========================================================================================
  251. // GLOBAL Functions
  252. //========================================================================================
  253.  
  254. #if qOldConfigurationFlags
  255. static void DefineConfiguration(Configuration& theConfiguration);
  256. #endif
  257.  
  258. //----------------------------------------------------------------------------------------
  259. // GetAlertButtonTitle: Retrieve the title of the button control. If itemNo isn't a
  260. // button, then return ''.
  261. //----------------------------------------------------------------------------------------
  262. #pragma segment MAGlobalsRes
  263.  
  264. void GetAlertButtonTitle(DialogRef theDialog,
  265.                          short itemNo,
  266.                          CStr255& theTitle)
  267. {
  268.     short itemType;
  269.     Handle item;
  270.     CRect box;
  271.     GetDialogItem(theDialog, itemNo, &itemType, &item, &box);
  272.  
  273.     if (itemType == (ctrlItem + btnCtrl))
  274.         GetControlTitle((ControlRef)item, theTitle);
  275.     else
  276.         theTitle.Empty();
  277. } // GetAlertButtonTitle 
  278.  
  279. //----------------------------------------------------------------------------------------
  280. // DoAlertKeyDown: Handle a keypress that has been mapped to one of the button controls.
  281. //----------------------------------------------------------------------------------------
  282. #pragma segment MAGlobalsRes
  283.  
  284. void DoAlertKeyDown(DialogRef theDialog, short itemNo)
  285. {
  286.     short itemType;
  287.     Handle item;
  288.     CRect box;
  289.  
  290.     GetDialogItem(theDialog, itemNo, &itemType, &item, &box);
  291.     if (itemType == (ctrlItem + btnCtrl))
  292.     {
  293.         // this code gives visual feedback 
  294.         HiliteControl((ControlRef)item, kControlUpButtonPart);    // hilite the button 
  295.  
  296.         long finalTicks;
  297.         Delay(8, &finalTicks);                                        // delay for 8 ticks 
  298.  
  299.         HiliteControl((ControlRef)item, kControlNoPart);        // stop hiliting the button 
  300.     }
  301. } // DoAlertKeyDown 
  302.  
  303. //----------------------------------------------------------------------------------------
  304. // CompareAlertKeysToItem: Compares the buffered multi-byte chars to the first character
  305. // of each button title 1st button in alert (by convention == "OK"). 2nd button in alert
  306. // (by convention == "Cancel"). 3rd button in alert (by convention == "No")
  307. //----------------------------------------------------------------------------------------
  308. #pragma segment MAGlobalsRes
  309.  
  310. Boolean CompareAlertKeysToItem(DialogRef theDialog,
  311.                                const CStr2& theChars,
  312.                                short& itemHit)
  313. {
  314.     Boolean returnVal = FALSE;
  315.  
  316.     static const short itemtests[3] = { ok, cancel, kNoButton };
  317.  
  318.     for (short i = 0; i < 4; i++)
  319.     {
  320.         CStr255 title;
  321.         GetAlertButtonTitle(theDialog, itemtests[i], title);
  322.         if (CompareMultiByteChars(theChars, title, FALSE))
  323.         {
  324.             itemHit = itemtests[i];
  325.             returnVal = TRUE;
  326.             break;
  327.         }
  328.     }
  329.  
  330.     return returnVal;
  331. } // CompareAlertKeysToItem 
  332.  
  333. //----------------------------------------------------------------------------------------
  334. // DrawDefaultProc:  Draw the thick rounded rectangle around the default button
  335. // (Imported to MacApp from Ponnuki by GA)
  336. //
  337. // This routine uses Keith Rollin's algorithm, as presented in the USENET Guide to
  338. // Programming the Macintosh. I have modified the basic algorithm only slightly--I add
  339. // two to the calculated 'buttonOval' value. This gets better results, particularly for
  340. // buttons of the default size (18 points).
  341. //----------------------------------------------------------------------------------------
  342. #pragma segment MAGlobalsRes
  343.  
  344. void DrawDefaultProc(DialogRef dlog)
  345. {
  346.     // Don't call GetDialogItem if the default button # has a strange value
  347.     short defaultButton = GetDialogDefaultItem(dlog);
  348.     if( defaultButton > 0 )
  349.     {
  350.         GrafPtr                savePort;
  351.         short                type = 0;
  352.         ControlRef            buttonHandle = NULL;
  353.         CRect                outlineBox;
  354.  
  355.         GetPort(&savePort);
  356.         SetPortWindowPort( dlog );
  357.  
  358.         GetDialogItem(dlog, defaultButton, &type, (Handle *) &buttonHandle, outlineBox);
  359.         outlineBox.Inset(CPoint(-4,-4));
  360.  
  361.         // Don't draw the bold outline around the default button
  362.         // unless it really is a button
  363.         if( type == ctrlItem + btnCtrl )
  364.         {
  365.             PenState            saveState;
  366.             short                buttonOval;
  367.             
  368.             GetPenState( &saveState );
  369.  
  370.             // We want to draw the thick line with a normal
  371.             // pen pattern that is 3 pixels wide
  372.             PenNormal();
  373.             PenSize(3,3);
  374.  
  375.             // If the button we are outlining is disabled,
  376.             // draw the outline with a gray pattern.
  377.             //•••SRF - Actually, on color systems we should use disable gray mode
  378.             if( (*buttonHandle)->contrlHilite == 255 )
  379.                 PenPat(&qd.gray);
  380.  
  381.  
  382.             // Calculate the curvature to use and draw the thick line
  383.             buttonOval = 2 + (outlineBox.bottom - outlineBox.top) / 2;
  384.             FrameRoundRect(outlineBox,buttonOval,buttonOval);
  385.             
  386.             SetPenState( &saveState );
  387.         }
  388.         SetPort(savePort);
  389.     }
  390. } // DrawDefaultProc
  391.  
  392. //----------------------------------------------------------------------------------------
  393. // MinimalAlertFilter: This is the minimally-functional alert filter that MacApp uses
  394. // in cases where gDispatcher has not yet been initialized.  TApplication.AlertFilter
  395. // calls this filter as well.
  396. //----------------------------------------------------------------------------------------
  397. #pragma segment MAGlobalsRes
  398.  
  399. pascal Boolean MinimalAlertFilter(DialogRef theDialog,
  400.                                   EventRecord& theEvent,
  401.                                   short& itemHit)
  402. {
  403.     Boolean returnValue = FALSE;
  404.     
  405.     switch(theEvent.what)
  406.     {
  407.         case updateEvt:
  408.             if (((DialogRef)theEvent.message) == theDialog)
  409.                 DrawDefaultProc(theDialog);
  410.             break;
  411.  
  412.         case keyDown:
  413.         {
  414.             static CStr2 bufferedCharacter; // hangs around in between keystrokes
  415.             unsigned char theChar = (unsigned char)(((theEvent.message) & charCodeMask));
  416.  
  417.             Boolean processCharacter = TRUE;
  418.             switch (MACharacterByteType((Ptr)&theChar, 0, smCurrentScript))
  419.             {
  420.                 case smFirstByte:
  421.                     processCharacter = FALSE;
  422.                     // no break - just drop through
  423.  
  424.                 case smSingleByte:
  425.                     bufferedCharacter = theChar;
  426.                     break;
  427.  
  428.                 case smLastByte:
  429.                     bufferedCharacter += theChar;
  430.                     break;
  431.             }
  432.             
  433.             if (processCharacter)
  434.             {
  435.                 if ((bufferedCharacter == chEnter) || (bufferedCharacter == chReturn))
  436.                 {
  437.                     itemHit = GetDialogDefaultItem(theDialog);
  438.                     DoAlertKeyDown(theDialog, itemHit);
  439.                     returnValue = TRUE;
  440.                 }
  441.                 else if ( (bufferedCharacter == '`') || (bufferedCharacter == chEscape) || ((bufferedCharacter == '.') && (theEvent.modifiers & cmdKey)))
  442.                 {
  443.                     DoAlertKeyDown(theDialog, cancel);
  444.                     itemHit = cancel;
  445.                     returnValue = TRUE;
  446.                 }
  447.             }
  448.             
  449.             break;
  450.         }
  451.     }
  452.     
  453.     return returnValue;
  454. } // MinimalAlertFilter 
  455.  
  456. //----------------------------------------------------------------------------------------
  457. // MacAppAlertFilter: 
  458. //----------------------------------------------------------------------------------------
  459. #pragma segment MAGlobalsRes
  460.  
  461. pascal Boolean MacAppAlertFilter(DialogRef theDialog,
  462.                                  EventRecord& theEvent,
  463.                                  short& itemHit)
  464. {
  465.     return gDispatcher ? gDispatcher->AlertFilter(theDialog, theEvent, itemHit) : MinimalAlertFilter(theDialog, theEvent, itemHit);
  466. } // MacAppAlertFilter 
  467.  
  468. //----------------------------------------------------------------------------------------
  469. // MacAppAppleEventIdleProc: 
  470. //----------------------------------------------------------------------------------------
  471. #pragma segment MAGlobalsRes
  472.  
  473. pascal Boolean MacAppAppleEventIdleProc(EventRecord& theEventRecord,
  474.                                         long& sleepTime,
  475.                                          RgnHandle& mouseRgn)
  476. {
  477.     if (gDispatcher)
  478.         return gDispatcher->AppleEventIdleProc(theEventRecord, sleepTime, mouseRgn);
  479.     else
  480.         return FALSE;
  481. } // MacAppAppleEventIdleProc 
  482.  
  483. //----------------------------------------------------------------------------------------
  484. // MacAppStandardFileFilter: 
  485. //----------------------------------------------------------------------------------------
  486. #pragma segment MAGlobalsRes
  487.  
  488. pascal Boolean MacAppStandardFileFilter(DialogRef theDialog,
  489.                                         EventRecord* theEvent,
  490.                                         short* itemHit,
  491.                                         void *yourDataPtr)
  492. {
  493.     if (gDispatcher)
  494.         return gDispatcher->StandardFileFilter(theDialog, *theEvent, *itemHit, yourDataPtr);
  495.     else
  496.         return FALSE;
  497. } // MacAppStandardFileFilter 
  498.  
  499. //----------------------------------------------------------------------------------------
  500. // ApplicationBeep: 
  501. //----------------------------------------------------------------------------------------
  502. #pragma segment MAGlobalsRes
  503.  
  504. void ApplicationBeep()
  505. {
  506.     if (gDispatcher)
  507.         gDispatcher->Beep(2);
  508.     else
  509.         SysBeep(2);
  510. } // ApplicationBeep 
  511.  
  512. //----------------------------------------------------------------------------------------
  513. // CleanupMacApp: 
  514. //----------------------------------------------------------------------------------------
  515. #pragma segment MAGlobalsRes
  516.  
  517. void CleanupMacApp(void)
  518. {
  519.     SetResLoad(TRUE);                            // Make sure segments can load 
  520.  
  521.     pETSPatch.UnpatchTrap();                    // Guaranteed not to fail 
  522.  
  523.     if (gDispatcher)
  524.         gDispatcher->Terminate();
  525.  
  526.     TBusyCursor::TerminateUBusyCursor();
  527.  
  528. /*    
  529. #if qContainer
  530.     if (gContainerLib)
  531.     {
  532.         CAShutdown();
  533.     }
  534. #endif
  535. */ 
  536.     
  537.     AEDisposeDesc(&gServerAddress);
  538.  
  539.     if (FailInfo::gTopHandler)
  540.         FailInfo::gTopHandler->Success();                    // Remove the outermost failure handler
  541.  
  542. //    #if qDebug
  543. //        DebugTerminate();
  544. //    #endif
  545.  
  546.     UnpatchAll();
  547.  
  548.     {
  549.         // Clear gDispatcher before freeing so nobody can 
  550.         // refer to the object while it is being destructed. 
  551.         TDispatcher* theDispatcher = gDispatcher;
  552.         gDispatcher = NULL;
  553.         FreeIfObject(theDispatcher);
  554.     }
  555.     
  556.     TOSADispatcher::fgDispatcher = (TOSADispatcher *)FreeIfObject(TOSADispatcher::fgDispatcher);
  557. } // CleanupMacApp 
  558.  
  559. //----------------------------------------------------------------------------------------
  560. // ExitToShellCleanupMacApp: 
  561. //----------------------------------------------------------------------------------------
  562. #pragma segment MAGlobalsRes
  563.  
  564. pascal void ExitToShellCleanupMacApp()
  565. {
  566.     long OldA5 = SetCurrentA5();                // ***** Called from trap patches *****
  567.  
  568.     ExitToShellType oldTrapAddr = (ExitToShellType) pETSPatch.GetOldTrapAddr();
  569.     CleanupMacApp();
  570.     CallExitToShellProc(oldTrapAddr);
  571.     
  572.     SetA5(OldA5);
  573. } // ExitToShellCleanupMacApp 
  574.  
  575. //----------------------------------------------------------------------------------------
  576. // DoneWithTemporaryRegion: Indicates that gTemporaryRegion is no longer in use. Call this
  577. // only if qDebug is true.
  578. //----------------------------------------------------------------------------------------
  579. #if qDebug
  580. #pragma segment MADebug
  581.  
  582. void DoneWithTemporaryRegion()
  583. {
  584.     if (!gBusyTemporaryRegion)
  585.         ProgramBreak("DoneWithTemporaryRegion called, but gTemporaryRegion is not locked");
  586.     gBusyTemporaryRegion = FALSE;
  587.     gUsedBy.Empty();
  588.     SetEmptyRgn(gTemporaryRegion);
  589. } // DoneWithTemporaryRegion 
  590.  
  591. #endif
  592.  
  593. //----------------------------------------------------------------------------------------
  594. // EnterDebugger: 
  595. //----------------------------------------------------------------------------------------
  596. #if qDebug
  597. #pragma segment MADebug
  598.  
  599. void EnterDebugger(Boolean entering)
  600. {
  601.     if (TBusyCursor::fgBusyCursor)
  602.         TBusyCursor::fgBusyCursor->Activate(!entering);
  603. } // EnterDebugger 
  604.  
  605. #endif
  606.  
  607. //----------------------------------------------------------------------------------------
  608. // ExitMacApp: 
  609. //----------------------------------------------------------------------------------------
  610. #pragma segment MATerminate
  611.  
  612. void ExitMacApp()
  613. {
  614.     ExitToShell();
  615.     // patch will call CleanupMacApp
  616.     
  617. } // ExitMacApp 
  618.  
  619. //----------------------------------------------------------------------------------------
  620. // GetNewCenteredDialog: 
  621. //----------------------------------------------------------------------------------------
  622. #pragma segment MAGlobalsRes
  623.  
  624. DialogRef GetNewCenteredDialog(ResNumber dialogID,
  625.                                Ptr dStorage,
  626.                                WindowRef behind)
  627. {
  628.     DialogTHndl dlogTemplate;
  629.  
  630.     SetCursor(&(qd.arrow));
  631.     
  632.     if (gDispatcher)
  633.         gDispatcher->InvalidateMouseRegions();
  634.         
  635.     dlogTemplate = (DialogTHndl)GetResource('DLOG', dialogID);
  636.     if (dlogTemplate)
  637.     {
  638.         CenterRectOnScreen(((CRect &) (*dlogTemplate)->boundsRect), TRUE, TRUE, TRUE);
  639.         return GetNewDialog(dialogID, dStorage, behind);
  640.     }
  641.     else
  642.     {
  643.         SysBeep(2);                                // At least give some indication 
  644. #if qDebug
  645.         CStr255 theString;
  646.         ConcatNumber("Unable to find 'DLOG' resource ", dialogID, theString);
  647.         ProgramBreak(theString);
  648. #endif
  649.  
  650.     }
  651.     return NULL;
  652. } // GetNewCenteredDialog 
  653.  
  654. //----------------------------------------------------------------------------------------
  655. // GetTextStyleFontInfo: Really a utility, but the gWorkPort isn't reachable from
  656. // UMacAppUtilities
  657. //----------------------------------------------------------------------------------------
  658. #pragma segment MAUtilitiesRes
  659.  
  660. void GetTextStyleFontInfo(const TextStyle& theTextStyle,
  661.                           FontInfo& theFontInfo,
  662.                           short& theFontHeight)
  663. {
  664.     GrafPtr savedPort;
  665.  
  666.     GetPort(&savedPort);
  667.     SetPortWindowPort(gWorkPort);
  668.     SetPortTextStyle(theTextStyle);
  669.     theFontHeight = MAGetFontInfo(theFontInfo);
  670.     SetPort(savedPort);
  671. } // GetTextStyleFontInfo 
  672.  
  673. #if qOldConfigurationFlags
  674.  
  675. //----------------------------------------------------------------------------------------
  676. // DefineConfiguration: 
  677. //----------------------------------------------------------------------------------------
  678. #pragma segment Main
  679.  
  680. void DefineConfiguration(Configuration& theConfiguration)
  681. {
  682.     theConfiguration.environsVersion = GetEnvironsVersion();
  683.     theConfiguration.machineType = GetMachineType();
  684.     theConfiguration.systemVersion = GetSystemVersion();
  685.     theConfiguration.processor = GetProcessor();
  686.     theConfiguration.hasFPU = HasFPU();
  687.     theConfiguration.hasColorQD = HasColorQD();
  688.     theConfiguration.has32BitQD = Has32BitQD();
  689.     theConfiguration.keyboardType = KeyboardType();
  690.     theConfiguration.atDrvrVersNum = GetATDrvrVersNum();
  691.     theConfiguration.hasSCSI = HasSCSI();
  692.     theConfiguration.hasAUX = HasAUX();
  693.     theConfiguration.hasTempMem = HasTempMem();
  694.     theConfiguration.teVersion = GetTEVersion();
  695.     theConfiguration.hasDesktopBus = HasDesktopBus();
  696.     theConfiguration.hasTrueType = HasTrueType();
  697.     theConfiguration.isOnlyBackground = IsOnlyBackground();
  698.     theConfiguration.isHighLevelEventAware = IsHighLevelEventAware();
  699.     theConfiguration.hasDragManager = HasDragManager();
  700.     theConfiguration.hasThreadManager = HasThreadManager();
  701.     theConfiguration.hasAOCEToolBox = HasAOCEToolBox();
  702.     theConfiguration.hasQDGXGraphics = HasQDGXGraphics();
  703.     theConfiguration.hasQDGXPrinting = HasQDGXPrinting();
  704.     #if 0
  705.         // Removed due to ASLM removal vs. deinstall problems.
  706.         theConfiguration.hasASLM = HasASLM();
  707.     #endif
  708.     theConfiguration.hasCFM = HasCFM();
  709.     theConfiguration.hasTranslationManager = HasTranslationManager();
  710.     theConfiguration.hasSpeechManager = HasSpeechManager();
  711.     theConfiguration.hasCustomFile = HasCustomFile();
  712.     theConfiguration.hasQuickTime = HasQuickTime();
  713.     theConfiguration.hasTSM = HasTSM();
  714.     theConfiguration.hasAppleScript = HasAppleScript();
  715. }
  716.  
  717. #endif // qOldConfigurationFlags
  718.  
  719. //----------------------------------------------------------------------------------------
  720. // InitUMacApp_Step1
  721. //----------------------------------------------------------------------------------------
  722. #pragma push
  723. #pragma processor 68000
  724. // Needs to be universal code
  725. #pragma segment Main
  726. // Must be in the Main segment since all other segments get unloaded from here.
  727.  
  728. void InitUMacApp_Step1()
  729. {
  730.     UniversalStartup(); // remove this to static initialization when possible
  731.  
  732.     // At this point the processor has been verified and "universal" code is no longer
  733.     // necessary when on 68k machines. Also, the toolbox has been initialized
  734.     
  735. #if qOldConfigurationFlags
  736.     DefineConfiguration(gConfiguration);
  737. #endif
  738.     if (!ValidateConfiguration())
  739.         AlertUnsupportedConfiguration();
  740.  
  741.     // Init the basics used by the ErrorMgr
  742.     gMacAppAlertFilter = (ProcPtr)MacAppAlertFilter;
  743. } // InitUMacApp_Step1 
  744.  
  745. #pragma pop
  746.  
  747. //----------------------------------------------------------------------------------------
  748. // InitUMacApp_Step3
  749. //----------------------------------------------------------------------------------------
  750. #pragma segment Main
  751. void InitUMacApp_Step3(short callsToMoreMasters)
  752. {
  753.     // Install MacApp's Memory management systems
  754.     InitCoreMacApp(callsToMoreMasters);
  755.  
  756.     DoInitUMacApp();                        // do rest of initialization 
  757.  
  758. #if qSegments
  759.     UnloadAllSegments();
  760. #endif
  761. } // InitUMacApp_Step3 
  762.  
  763. //----------------------------------------------------------------------------------------
  764. // DoInitUMacApp: Must be in the init segment; unloaded at start of event loop
  765. //----------------------------------------------------------------------------------------
  766. #pragma segment MAInit
  767.  
  768. void DoInitUMacApp()
  769. {
  770.     // Initialize runtime support for objects 
  771.     InitUObject();
  772. #if qDebug || qTheDebugger
  773.     InitUDebug();
  774. #endif
  775.  
  776.     // assign the global text style records from resources
  777.     MAGetTextStyle(kSystemFontTextStyle, gSystemStyle);
  778.     MAGetTextStyle(kApplFont12TextStyle, gApplicationStyle);
  779.     MAGetTextStyle(kApplFont9TextStyle, gApplicationStyle9);
  780.  
  781.     //    atexit(&CleanupMacApp);
  782.     pETSPatch.Install(ExitToShellCleanupMacApp);
  783.  
  784.     // Initialize the view system
  785.     Boolean initGX = FALSE;
  786. #if qGXViews || qGXPrinting
  787.     initGX = TRUE;
  788. #endif
  789.     TView::InitUView(initGX);
  790.  
  791.     // Other 1-time initialization 
  792.     gTemporaryRegion = MakeNewRgn();
  793.  
  794.     // Create a work port for our convenience 
  795.     if (qNeedsColorQD || HasColorQD())
  796.         gWorkPort = NewCWindow(NULL, gZeroRect, gEmptyString, FALSE, documentProc, NULL, FALSE, 0);
  797.     else
  798.         gWorkPort = NewWindow(NULL, gZeroRect, gEmptyString, FALSE, documentProc, NULL, FALSE, 0);
  799.  
  800. #if !qModelCFM
  801.     TBusyCursor::InitUBusyCursor();
  802. #endif
  803.     
  804. #if qContainer
  805.     InstallContainerLib();
  806. #endif
  807.  
  808.     TPrintHandler::gNullPrintHandler = new TPrintHandler;
  809.     TPrintHandler::gNullPrintHandler->IPrintHandler(NULL);
  810.  
  811.     TPrintHandler::gPrintHandler = TPrintHandler::gNullPrintHandler;
  812.  
  813. #if qTemplateViews
  814.     {
  815.         // =============================================== 
  816.         // Suppress Linker dead stripping of these classes 
  817.  
  818.         MA_REGISTER_CLASS(TDragDropBehavior);
  819.  
  820.         // =============================================== 
  821.  
  822.         MA_REGISTER_SIGNATURE(TView, kStdView);
  823.         MA_REGISTER_SIGNATURE(TView, kStdDefaultView);
  824.         MA_REGISTER_SIGNATURE(TIncludeView, kStdIncludeAt);
  825.         MA_REGISTER_SIGNATURE(TWindow, kStdWindow);
  826.         MA_REGISTER_SIGNATURE(TScrollBar, kStdScrollBar);
  827.         MA_REGISTER_SIGNATURE(TScrollerScrollBar, kStdScrollerScrollBar);
  828.         MA_REGISTER_SIGNATURE(TScroller, kStdScroller);
  829.  
  830.         MA_REGISTER_SIGNATURE(TTracker, kStdTracker);
  831.         MA_REGISTER_SIGNATURE(TList, kStdList);
  832.         MA_REGISTER_SIGNATURE(TDrawingEnvironment, kStdDrawingEnvironment);
  833.     }
  834. #endif
  835.     
  836. #if qDebug
  837.     // The linker optimizes away the meta information for the following classes by
  838.     // stripping the ClassInfoProc. MacApp does a SetEltType on lists containing these
  839.     // classes which requires meta information. Suppress the optimization by doing
  840.     // suppressing dead stripping. (See UApplication.cp)
  841.     
  842.     MA_REGISTER_CLASS(TDocument);
  843.     MA_REGISTER_CLASS(TEvent);
  844.     MA_REGISTER_CLASS(TClientCommand);
  845. #endif
  846.  
  847.     InitUAdorners();                            // Temporarily needed for debug window 
  848.  
  849.     TUndoHandler::InitUUndo();
  850.     
  851.     InitUMenuMgr();
  852.     InitUClipboardMgr();
  853.  
  854.     // create gServerAddress
  855.     ProcessSerialNumber psn;
  856.     psn.highLongOfPSN = 0;
  857.     psn.lowLongOfPSN = kCurrentProcess;
  858.     FailOSErr(AECreateDesc(typeProcessSerialNumber, (Ptr) &psn, sizeof(ProcessSerialNumber), &gServerAddress));
  859.  
  860.     // initialize the pseudo-random sequence generation function
  861.     unsigned long time;
  862.     GetDateTime(&time);
  863.     srand((unsigned int)time);
  864.  
  865. #if qDebug
  866.     //InitUDialog(); //Necessary for debug dialog.
  867. #if qPerform
  868.     InitUTEView();
  869. #endif
  870. #endif
  871.  
  872. } // DoInitUMacApp 
  873.  
  874. //----------------------------------------------------------------------------------------
  875. // InstallIfPrintHandler: 
  876. //----------------------------------------------------------------------------------------
  877. #pragma segment MARes
  878.  
  879. void InstallIfPrintHandler(TPrintHandler* aPrintHandler,
  880.                            TView* aView)
  881.  
  882. {
  883.     // Install a copy of aPrintHandler into the view.  aPrintHandler will be a real printhandler
  884.     // if UPrinting has been initialized otherwise it is a NULL print handler.
  885.     if ((aPrintHandler) && (aView) && (aPrintHandler != TPrintHandler::gNullPrintHandler) && (TPrintHandler::gPrintHandler != TPrintHandler::gNullPrintHandler))
  886.     {
  887.         TPrintHandler * aNewPrintHandler = (TPrintHandler *)aPrintHandler->Clone();// signals failure if can't clone
  888.  
  889.         aNewPrintHandler->fView = aView;
  890.         if (aView->fDocument)
  891.             aNewPrintHandler->fDocument = aView->fDocument; // so the printinfo can be shared if necessary
  892.  
  893.         aNewPrintHandler->SetDefaultPrintInfo(); // do this after we have a document (if any)
  894.  
  895.         //
  896.         // Now do the attachments
  897.         //
  898.         if (aView->fDocument)
  899.             aView->fDocument->AttachPrintHandler(aNewPrintHandler);
  900.         aView->AttachPrintHandler(aNewPrintHandler);
  901.     }
  902. } // InstallIfPrintHandler 
  903.  
  904. //----------------------------------------------------------------------------------------
  905. // MakeNewRgn: 
  906. //----------------------------------------------------------------------------------------
  907. #pragma segment MAGlobalsRes
  908.  
  909. RgnHandle MakeNewRgn()
  910. {
  911.     RgnHandle aRgn = NewRgn();
  912.     FailNIL(aRgn);
  913.     return aRgn;
  914. } // MakeNewRgn 
  915.  
  916. //----------------------------------------------------------------------------------------
  917. // DetermineClassDesc: 
  918. //----------------------------------------------------------------------------------------
  919. #pragma segment MAOpen
  920.  
  921. const ClassDesc* DetermineClassDesc(IDType signature, const ClassName& className)
  922. {
  923.     if (className.IsEmpty())
  924.         return ClassDesc::GetClassDescFromSignature(signature);
  925.     else
  926.         return ClassDesc::GetClassDescFromClassName(className);
  927. } // DetermineClassDesc 
  928.  
  929. //----------------------------------------------------------------------------------------
  930. // GetClassDescFromSignature: 
  931. //----------------------------------------------------------------------------------------
  932. #pragma segment MAOpen
  933.  
  934. const ClassDesc* GetClassDescFromSignature(IDType signature)
  935. {
  936.     return ClassDesc::GetClassDescFromSignature(signature);
  937. }
  938.  
  939. //----------------------------------------------------------------------------------------
  940. // NewStdObject: 
  941. //----------------------------------------------------------------------------------------
  942. #pragma segment MAOpen
  943.  
  944. TObject* NewStdObject(IDType signature)
  945. {
  946.     return (TObject*) ClassDesc::NewBySignature(signature);
  947. }
  948.  
  949. //----------------------------------------------------------------------------------------
  950. // NewObjectBySignature: 
  951. //----------------------------------------------------------------------------------------
  952. #pragma segment MAOpen
  953.  
  954. TObject* NewObjectBySignature(IDType signature,
  955.                               const ClassName& className)
  956. {
  957.     if (className.IsEmpty())
  958.         return (TObject*) ClassDesc::NewBySignature(signature);
  959.     else
  960.         return (TObject*) ClassDesc::NewByClassName(className);
  961. }
  962.  
  963. //----------------------------------------------------------------------------------------
  964. // FindPos: 
  965. //----------------------------------------------------------------------------------------
  966. #pragma segment MAGlobalsRes
  967.  
  968. short FindPos(const CStr255& pattern, CStr255& source)
  969. {
  970.     short i = 0;
  971.     short j = 0;
  972.     short position = 0;
  973.  
  974.     do
  975.     {
  976.         ++i;
  977.         position = i;
  978.         for (j = 1; j <= pattern.Length(); ++j)
  979.             if (!((source[i + j - 1] == pattern[j]) && (MACharacterByteType((Ptr)&source[1], i + j - 2, smCurrentScript) == MACharacterByteType((Ptr)&pattern[1], j - 1, smCurrentScript))))
  980.             {
  981.                 position = 0;
  982.                 break;
  983.             }
  984.     } while (!((position > 0) || (i >= source.Length() - pattern.Length() + 1)));
  985.  
  986.     return position;
  987. } // FindPos 
  988.  
  989.  
  990. //----------------------------------------------------------------------------------------
  991. // ParseTitleTemplate: 
  992. //----------------------------------------------------------------------------------------
  993. Boolean ParseTitleTemplate(CStr255& itsTemplate,
  994.                            short& preDocname,
  995.                            short& constTitle)
  996.  
  997. {
  998.     const CStr255 kPreDocname = "<<<";
  999.     const short kPreSize = 3;
  1000.     const CStr255 kPostDocname = ">>>";
  1001.     const short kPostSize = 3;
  1002.  
  1003.     if (itsTemplate.IsEmpty())
  1004.     {
  1005.         preDocname = 1;
  1006.         constTitle = 0;
  1007.     }
  1008.     else
  1009.     {
  1010.         preDocname = FindPos(kPreDocname, itsTemplate);
  1011.         if (preDocname > 0)
  1012.         {
  1013.             itsTemplate.Delete(preDocname, kPreSize);
  1014.             short x = FindPos(kPostDocname, itsTemplate);
  1015.             if (x == 0)
  1016.                 constTitle = preDocname - 1;
  1017.             else
  1018.             {
  1019.                 itsTemplate.Delete(x, kPostSize);
  1020.                 constTitle = itsTemplate.Length() - x + preDocname;
  1021.             }
  1022.         }
  1023.     }
  1024.  
  1025.     return preDocname > 0;
  1026. } // ParseTitleTemplate 
  1027.  
  1028. //----------------------------------------------------------------------------------------
  1029. // RegisterStdType: Register or re-register a type and a class
  1030. //----------------------------------------------------------------------------------------
  1031. #pragma segment MAGlobalsRes
  1032.  
  1033. void RegisterStdType(const CStr255& typeName,
  1034.                      IDType signature)
  1035. {
  1036.     // If the name can't be found it was probably misspelled or dead-stripped 
  1037.     const ClassDesc* itsClassDesc = ClassDesc::GetClassDescFromClassName(typeName);
  1038.     if (itsClassDesc == NULL)
  1039.         Failure(minErr, 0);
  1040.  
  1041.     // break const-ness
  1042.     ((ClassDesc*) itsClassDesc)->RegisterSignature(signature);
  1043. }
  1044.  
  1045. //----------------------------------------------------------------------------------------
  1046. // GetStandardType: 
  1047. //----------------------------------------------------------------------------------------
  1048. #pragma segment MAGlobalsRes
  1049.  
  1050. IDType GetStandardType(const ClassDesc* itsClassDesc)
  1051. {
  1052.     return (itsClassDesc != NULL) ? itsClassDesc->GetSignature() : kNoIdentifier;
  1053. }
  1054.  
  1055. //----------------------------------------------------------------------------------------
  1056. // SubstituteInTitle: 
  1057. //----------------------------------------------------------------------------------------
  1058. #pragma segment MAGlobalsRes
  1059.  
  1060. Boolean SubstituteInTitle(CStr255& title,
  1061.                           const CStr255& newStuff,
  1062.                           short preDocname,
  1063.                           short constTitle)
  1064. {
  1065.     if (preDocname > 0)
  1066.     {
  1067.         if (constTitle == 0)
  1068.             title = newStuff;
  1069.         else
  1070.         {
  1071.             title.Delete(preDocname, title.Length() - constTitle);
  1072.             title.Insert(newStuff, preDocname);
  1073.         }
  1074.         return TRUE;
  1075.     }
  1076.     else
  1077.         return FALSE;
  1078. } // SubstituteInTitle 
  1079.  
  1080. //----------------------------------------------------------------------------------------
  1081. // UseTemporaryRegion: Call this when you are about to use gTemporaryRegion and qDebug is
  1082. // true. Used with DoneWithTemporaryRegion will prevent you from trying to use
  1083. // gTemporaryRegion from two places at the same time.
  1084. //----------------------------------------------------------------------------------------
  1085. #if qDebug
  1086. #pragma segment MADebug
  1087.  
  1088. void UseTemporaryRegion(const CStr255& byWhom)
  1089. {
  1090.     if (gBusyTemporaryRegion)
  1091.     {
  1092.         fprintf(stderr, "'%s' is trying to lock gTemporaryRegion,", (const char*)byWhom);
  1093.         fprintf(stderr, "but it is already locked by '%s'\n", (const char*)gUsedBy);
  1094.         ProgramBreak("Error in UseTemporaryRegion");
  1095.     }
  1096.     else
  1097.     {
  1098.         gBusyTemporaryRegion = TRUE;
  1099.         gUsedBy = byWhom;
  1100.     }
  1101. } // UseTemporaryRegion 
  1102.  
  1103. #endif
  1104.  
  1105.  
  1106. //========================================================================================
  1107. // CLASS CTemporaryRegion
  1108. //========================================================================================
  1109. #undef Inherited
  1110.  
  1111. //----------------------------------------------------------------------------------------
  1112. // CTemporaryRegion::new: 
  1113. //----------------------------------------------------------------------------------------
  1114. #pragma segment MAGlobalsRes
  1115.  
  1116. void* CTemporaryRegion::operator new(size_t /*size*/)
  1117. {
  1118.     return NULL; // prevent heap-based allocation
  1119. }
  1120.  
  1121. //----------------------------------------------------------------------------------------
  1122. // CTemporaryRegion::delete: 
  1123. //----------------------------------------------------------------------------------------
  1124. #pragma segment IteratorRes
  1125.  
  1126. void CTemporaryRegion::operator delete(void*)
  1127. {
  1128. }
  1129.  
  1130. //----------------------------------------------------------------------------------------
  1131. // CTemporaryRegion::CTemporaryRegion: 
  1132. //----------------------------------------------------------------------------------------
  1133. #pragma segment MAGlobalsRes
  1134.  
  1135. CTemporaryRegion::CTemporaryRegion()
  1136. {
  1137.     // Simple single level cache for first cut
  1138.     // take the cached region if available otherwise make one up to give out
  1139.     if (fCachedRgn)
  1140.     {
  1141.         fRgnHandle = fCachedRgn;
  1142.         fCachedRgn = NULL;
  1143.     }
  1144.     else
  1145.     {
  1146.         fRgnHandle = MakeNewRgn();
  1147.     }
  1148.  
  1149.     // Setup the FailInfo to catch any failures while this object is in scope
  1150.     fFailInfo.SetCleanupProc(CTemporaryRegion::CallCleanup, this);
  1151. } // CTemporaryRegion::CTemporaryRegion 
  1152.  
  1153. //----------------------------------------------------------------------------------------
  1154. // CTemporaryRegion::~CTemporaryRegion: 
  1155. //----------------------------------------------------------------------------------------
  1156. #pragma segment MAGlobalsRes
  1157.  
  1158. CTemporaryRegion::~CTemporaryRegion()
  1159. {
  1160.     this->Cleanup();
  1161.  
  1162.     fFailInfo.Success();
  1163. } // CTemporaryRegion::~CTemporaryRegion 
  1164.  
  1165. //----------------------------------------------------------------------------------------
  1166. // CTemporaryRegion::Cleanup: 
  1167. //----------------------------------------------------------------------------------------
  1168. #pragma segment MAGlobalsRes
  1169.  
  1170. void CTemporaryRegion::Cleanup()
  1171. {
  1172.     // return to the cache if not already full
  1173.     if (fCachedRgn)
  1174.     {
  1175.         fRgnHandle = DisposeIfRgnHandle(fRgnHandle);
  1176.     }
  1177.     else
  1178.     {
  1179.         fCachedRgn = fRgnHandle;
  1180.         fRgnHandle = NULL;
  1181.     }
  1182. } // CTemporaryRegion::Cleanup 
  1183.  
  1184. //----------------------------------------------------------------------------------------
  1185. // CTemporaryRegion::CallCleanup: 
  1186. //----------------------------------------------------------------------------------------
  1187. #pragma segment MAGlobalsRes
  1188.  
  1189. /*static*/ void CTemporaryRegion::CallCleanup(void* context)
  1190. {
  1191.     ((CTemporaryRegion*) context)->Cleanup();
  1192. } // CTemporaryRegion::CallCleanup 
  1193.  
  1194. //========================================================================================
  1195. // GLOBAL Procedures
  1196. //========================================================================================
  1197. #undef Inherited
  1198.  
  1199. //----------------------------------------------------------------------------------------
  1200. // GetSysVolume: 
  1201. //----------------------------------------------------------------------------------------
  1202. #pragma segment MAGlobalsRes
  1203.  
  1204. OSErr GetSysVolume(short& vRefNum)
  1205. {
  1206.     long dir;
  1207.  
  1208.     return FindFolder(kOnSystemDisk, kSystemFolderType, FALSE, &vRefNum, &dir);
  1209. } // GetSysVolume 
  1210.  
  1211.  
  1212. //----------------------------------------------------------------------------------------
  1213. // GetIndVolume: 
  1214. //----------------------------------------------------------------------------------------
  1215. #pragma segment MAGlobalsRes
  1216.  
  1217. OSErr GetIndVolume(short index,
  1218.                    short& vRefNum)
  1219. {
  1220.     ParamBlockRec pb;
  1221.     OSErr err;
  1222.  
  1223.     pb.volumeParam.ioCompletion = NULL;
  1224.     pb.volumeParam.ioNamePtr = NULL;
  1225.     pb.volumeParam.ioVolIndex = index;
  1226.  
  1227.     err = PBGetVInfoSync(&pb);
  1228.  
  1229.     vRefNum = pb.volumeParam.ioVRefNum;
  1230.     return err;
  1231. } // GetIndVolume 
  1232.  
  1233.  
  1234. //----------------------------------------------------------------------------------------
  1235. // VolHasDesktopDB: 
  1236. //----------------------------------------------------------------------------------------
  1237. #pragma segment MAGlobalsRes
  1238.  
  1239. OSErr VolHasDesktopDB(short vRefNum, Boolean& hasDesktop)
  1240. {
  1241.     HParamBlockRec pb;
  1242.     GetVolParmsInfoBuffer info;
  1243.  
  1244.     pb.ioParam.ioCompletion = NULL;
  1245.     pb.ioParam.ioVRefNum = vRefNum;
  1246.     pb.ioParam.ioNamePtr = NULL;
  1247.     pb.ioParam.ioBuffer = (Ptr) & info;
  1248.     pb.ioParam.ioReqCount = sizeof(GetVolParmsInfoBuffer);
  1249.  
  1250.     OSErr err = ::PBHGetVolParmsSync(&pb);
  1251.  
  1252.     hasDesktop = (err == noErr) && ((info.vMAttrib & (1L << bHasDesktopMgr)) != 0);
  1253.  
  1254.     return err;
  1255.     
  1256. } // VolHasDesktopDB 
  1257.  
  1258.  
  1259. //----------------------------------------------------------------------------------------
  1260. // FindAppOnVolume: 
  1261. //----------------------------------------------------------------------------------------
  1262. #pragma segment MAGlobalsRes
  1263.  
  1264. OSErr FindAppOnVolume(OSType sig,
  1265.                       short vRefNum,
  1266.                       FSSpec& thefile)
  1267. {
  1268.     DTPBRec pb;
  1269.     OSErr err;
  1270.  
  1271.     pb.ioCompletion = NULL;
  1272.     pb.ioVRefNum = vRefNum;
  1273.     pb.ioNamePtr = NULL;
  1274.     if ((err = PBDTGetPath(&pb)) != noErr)
  1275.         return err;                                    // Puts DT refnum into pb.ioDTRefNum
  1276.     short refNum = pb.ioDTRefNum;
  1277.  
  1278.     pb.ioCompletion = NULL;
  1279.     pb.ioDTRefNum = refNum;
  1280.     pb.ioIndex = 0;
  1281.     pb.ioFileCreator = sig;
  1282.     pb.ioNamePtr = (StringPtr) thefile.name;
  1283.     err = PBDTGetAPPLSync(&pb);                        // Find it!
  1284.  
  1285.     if( err == fnfErr )
  1286.         err = afpItemNotFound;                        // Bug in PBDTGetAPPL
  1287.     if( err )
  1288.         return err;                                    // Returns afpItemNotFound if app wasn't found.
  1289.  
  1290.     thefile.vRefNum = vRefNum;
  1291.     thefile.parID = pb.ioAPPLParID;
  1292.     return err;
  1293. } // FindAppOnVolume 
  1294.  
  1295. //----------------------------------------------------------------------------------------
  1296. // LaunchAppByFSSpec: 
  1297. //----------------------------------------------------------------------------------------
  1298. #pragma segment MAGlobalsRes
  1299.  
  1300. OSErr LaunchAppByFSSpec(const FSSpec& fileSpec,
  1301.                            LaunchFlags launchControlFlags,
  1302.                            ProcessSerialNumber& psn)
  1303. {
  1304.     LaunchParamBlockRec pb;
  1305.     OSErr err;
  1306.     FSSpec localFSSpec = fileSpec;        // so we can take its address below
  1307.  
  1308.     pb.launchBlockID = extendedBlock;
  1309.     pb.launchEPBLength = extendedBlockLen;
  1310.     pb.launchFileFlags = launchNoFileFlags;
  1311.     pb.launchControlFlags = launchControlFlags | launchNoFileFlags;
  1312.     pb.launchAppSpec = &localFSSpec;
  1313.     pb.launchAppParameters = NULL;
  1314.  
  1315.     err = LaunchApplication(&pb);
  1316.     if (err == noErr)
  1317.         psn = pb.launchProcessSN;
  1318.     return err;
  1319. } // LaunchAppByFSSpec 
  1320.  
  1321.  
  1322. //----------------------------------------------------------------------------------------
  1323. // LaunchBySignature: 
  1324. //----------------------------------------------------------------------------------------
  1325. #pragma segment MAGlobalsRes
  1326.  
  1327. OSErr LaunchBySignature(OSType sig,
  1328.                         ProcessSerialNumber& psn,
  1329.                         FSSpec* fileSpec,
  1330.                         Boolean* launched,
  1331.                         Boolean allowLaunch,
  1332.                         LaunchFlags launchControlFlags)
  1333. {
  1334.     OSErr err;
  1335.     short sysVRefNum;
  1336.  
  1337.     // First see if it's already running:
  1338.  
  1339.     if (launched)
  1340.         *launched = FALSE;
  1341.     err = FindProcessBySignature(sig, psn, fileSpec);
  1342.  
  1343.     if (err == noErr)
  1344.         if ((launchControlFlags & launchDontSwitch) == 0)
  1345.             return SetFrontProcess(&psn);        // They wanted to switch to it…
  1346.  
  1347.     if (err != procNotFound || !allowLaunch)
  1348.         return err;
  1349.  
  1350.     // Well, it's not running but it's okay to launch it. Let's have a look around:
  1351.  
  1352.     if ((err = GetSysVolume(sysVRefNum)) != noErr)
  1353.         return err;                                    // Find boot volume
  1354.     short vRefNum = sysVRefNum;                        // Start search with boot volume
  1355.     short index = 0;
  1356.     do
  1357.     {
  1358.         if (index == 0 || vRefNum != sysVRefNum)
  1359.         {
  1360.             Boolean hasDesktopDB;
  1361.  
  1362.             if ((err = VolHasDesktopDB(vRefNum, hasDesktopDB)) != noErr)
  1363.                 return err;
  1364.             if (hasDesktopDB)
  1365.             {
  1366.                 FSSpec file;
  1367.  
  1368.                 // If volume has a desktop DB,
  1369.                 err = FindAppOnVolume(sig, vRefNum, file);    // ask it to find app
  1370.                 if (err == noErr)
  1371.                 {
  1372.                     // If found,
  1373.                     if (fileSpec)
  1374.                         *fileSpec = file;
  1375.                     if (launched)
  1376.                         *launched = TRUE;
  1377.                     return LaunchAppByFSSpec(file, launchControlFlags, psn);    // Launch it!
  1378.                 }
  1379.                 else if (err != afpItemNotFound && err != paramErr /* in case of Volume with no files (audio CD) */)
  1380.                     return err;
  1381.             }
  1382.         }
  1383.         err = GetIndVolume(++index, vRefNum);    // Else go to next volume
  1384.     } while (err == noErr);                        // Keep going until we run out of vols
  1385.  
  1386.     if( err==nsvErr || err==afpItemNotFound )
  1387.         err= fnfErr;                                    // File not found on any volume
  1388.     return err;
  1389. } // LaunchBySignature 
  1390.  
  1391. //----------------------------------------------------------------------------------------
  1392. // End of UMacAppGlobals.cp
  1393.  
  1394. #pragma segment Inline
  1395.